package net.ib.mtalk.service;

import java.util.List;

import net.ib.mntalk.protocol.Common;
import net.ib.mntalk.protocol.Common.BuddyChange;
import net.ib.mntalk.protocol.Common.BuddyInfo;
import net.ib.mntalk.protocol.Common.NotificationInfo;
import net.ib.mntalk.protocol.Common.UUIDMsg;
import net.ib.mntalk.protocol.Common.UUIDSliceRange;
import net.ib.mntalk.protocol.Session.GetBuddyChangesReq;
import net.ib.mntalk.protocol.Session.GetBuddyChangesRes;
import net.ib.mntalk.protocol.Session.GetBuddyInfosReq;
import net.ib.mntalk.protocol.Session.GetBuddyInfosRes;
import net.ib.mntalk.protocol.Session.GetViewPropertiesRes;
import net.ib.mntalk.protocol.Session.GetViewsChangesRes;
import net.ib.mntalk.protocol.Session.GetViewsRes;
import net.ib.mtalk.database.helper.BuddyDatabaseHelper;
import net.ib.mtalk.global.GlobalPreferences;
import net.ib.mtalk.network.NetResultReceiver;
import net.ib.mtalk.network.TcpClient;
import net.ib.mtalk.network.TcpEnvelope;
import net.ib.mtalk.network.MethodId.Session;
import net.ib.mtalk.network.NetResultReceiver.Receiver;
import net.ib.mtalk.network.serverapi.Ping;
import net.ib.mtalk.network.task.GetBuddyChangesTask;
import net.ib.mtalk.network.task.GetBuddyInfosTask;
import net.ib.mtalk.network.task.ProfileDownloadTask;
import net.ib.mtalk.service.ViewChangeHandler.ViewChangeCallback;
import net.ib.mtalk.util.MTalkLogWriter;
import net.ib.mtalk.util.ProfileImageLoader;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.widget.MultiAutoCompleteTextView;

public class BuddyChangeHandler extends SelectResultHandler {
	
	// 종료를 위한 수행 카운터
	private int mFinishCount;
	
	private NotificationInfo mNotiInfo;
	private Context mContext;
	private Handler mHandler;

	/**
	 * 한 개의 NotificationInfo에 대하여 객체가 한 개씩 생성된다.
	 * @param notificationInfo {@link Common#BUDDY_CHANGED}에 해당하는 객체
	 */
	BuddyChangeHandler(Context context, NotificationInfo notificationInfo) {
		super(context, notificationInfo);
		mNotiInfo = notificationInfo;
		mContext = context;
		mFinishCount = 0;
	}

	@Override
	protected void onWork(Handler handler) {
		mHandler = handler;
		
		UUIDSliceRange range = new UUIDSliceRange();
		range.setStart(GlobalPreferences.getLastBuddyChangedNotiUuid());
		range.setEnd(mNotiInfo.getNotiId().getNotiUuid());
		range.setAscending(true);	// 내림차순
		range.setMaxCount(50);
		
		GetBuddyChangesReq getBuddyChangesReq = new GetBuddyChangesReq();
		getBuddyChangesReq.setRange(range);
		
		// TcpEnvelope!
		TcpEnvelope reqEnvelope = new TcpEnvelope.Builder()
			.setType(TcpEnvelope.REQUEST)
			.setMethodId(Session.Contact.GetBuddyChanges)
			.setMessage(getBuddyChangesReq)
			.setCallback(makeNewCallback())
			.build();

		// Send!
		TcpClient.send(reqEnvelope);
	}
	
	private NetResultReceiver mCallback = null;
	
	protected NetResultReceiver makeNewCallback() {
		if(mCallback == null){
			mCallback = new NetResultReceiver(mHandler, new BuddyChangeCallback());
		}
		return mCallback;
	}
	
	class BuddyChangeCallback implements NetResultReceiver.Receiver {

		@Override
		public void onNetResult(int resultCode, Object sentObject,
				Object receivedObject) {
			if (resultCode != NetResultReceiver.TCP_RESULT) {	// 그냥 예외 체크
				MTalkLogWriter.e("BuddyChangeHandler.BuddyChangeCallback.onNetResult(): Should not reach here. It's not tcp result");
				return;
			}
			try{
				TcpEnvelope recvEnvelope = (TcpEnvelope) receivedObject;
				// 네트워크 결과에 따른 분기
				switch (recvEnvelope.getMethodId()) {
				case net.ib.mtalk.network.MethodId.Session.Contact.GetBuddyChanges:
					GetBuddyChangesRes res = (GetBuddyChangesRes)recvEnvelope.getMessage();
					if(res.getResponseCode() == Common.EXPIRED_CACHE){
						Log.i("ZOO", "EXPIRED_CACHE");
						getAllBuddies();
						break;
					}
					onGetBuddyChangesResult(res);
					break;
				case net.ib.mtalk.network.MethodId.Session.Contact.GetBuddyInfos:
					onGetBuddyInfosResult((GetBuddyInfosRes) recvEnvelope.getMessage());
					break;
				}
			} catch (Exception e) {
				finishMyJob();
				MTalkLogWriter.e(e);
			}
		}

		@Override
		public void onNetError(int resultCode, Object sentObject) {
			finishMyJob();
		}
	}
	
	protected void onGetBuddyInfosResult(GetBuddyInfosRes getBuddyInfosRes) {
		if(getBuddyInfosRes.getResponseCode() == Common.SUCCESS) {
			BuddyDatabaseHelper.insertGetBuddies(mContext, getBuddyInfosRes);
			for(int i=0; i < getBuddyInfosRes.getBuddyInfoCount(); i++){
				BuddyInfo info = getBuddyInfosRes.getBuddyInfo(i);
				if(info.getProfile().getProfileImage() == null) {
					BuddyDatabaseHelper.updateBuddyImage(mContext, info.getUserUuid(), true);
					continue;
				}
				if(info.getProfile().getProfileImage().getFileName().equals("null")){
					ProfileImageLoader.getInstance(mContext).deleteImage(info.getUserUuid());
					continue;
				}
				ProfileDownloadTask task = new ProfileDownloadTask(mContext, new Handler(), info.getUserUuid(), 
										info.getProfile().getProfileImage(),
										null,
//										new File.ImageSize().setHeight(GraphicUtil.IMAGE_SIZE_BUDDY_PROFILE).setWidth(GraphicUtil.IMAGE_SIZE_BUDDY_PROFILE), 
										-1, 1);
				task.execute();
			}
		}
		finishMyJob();
	}

	protected void onGetBuddyChangesResult(GetBuddyChangesRes getBuddyChangesRes) {
		if(getBuddyChangesRes.getResponseCode() != Common.SUCCESS) {
			finishMyJob();
			return;
		}
		mFinishCount = getBuddyChangesRes.getBuddyChangeCount();
		
		if(mFinishCount == 0){
			finishMyJob();
		}
		
		// 변경된 사항에 대해서 properties 를 요청한다.
		for(int i = 0; i < getBuddyChangesRes.getBuddyChangeCount() ; i++){
			BuddyChange buddyChange = getBuddyChangesRes.getBuddyChange(i);
			UUIDMsg buddyUUID = buddyChange.getBuddyUuid();
//			List<Integer> buddyPropertyList = buddyChange.getPropertyList();
//			if(buddyPropertyList.contains(Common.USER_PROPERTY_PROFILE_IMAGE)){
//				// 이미지 변경
//				
//			}
			switch (buddyChange.getType()) {
			case Common.ADDED:
				Log.i("ZOO", "ADD");
			case Common.MODIFIED:
				Log.i("ZOO", "MODIFIED");
				callGetBuddyInfos(buddyUUID);
				break;

			case Common.REMOVED:
				Log.i("ZOO", "REMOVED");
				BuddyDatabaseHelper.removeBuddy(mContext, buddyUUID);
				if(buddyChange.hasNotiUuid()){
					GlobalPreferences.setLastBuddyChangedNotiUUID(buddyChange.getNotiUuid());
				}
				finishMyJob();
				break;
				
				/*GetBuddyInfosReq getBuddyChangesReq1 = new GetBuddyInfosReq();
				getBuddyChangesReq1.setPredicate(new Common.UUIDSlicePredicate().addId(buddyUUID));
				getBuddyChangesReq1.addProperty(Common.USER_PROPERTY_NAME)
								   .addProperty(Common.USER_PROPERTY_PROFILE_IMAGE)
							       .addProperty(Common.USER_PROPERTY_BIRTHDAY)
								   .addProperty(Common.USER_PROPERTY_STATUS);
				
				// TcpEnvelope!
				TcpEnvelope reqEnvelope1 = new TcpEnvelope.Builder()
					.setType(TcpEnvelope.REQUEST)
					.setMethodId(Session.Contact.GetBuddyInfos)
					.setMessage(getBuddyChangesReq1)
					.setCallback(makeNewCallback())
					.build();
				// Send!
				TcpClient.send(reqEnvelope1);
				break;*/
			}
		}
	}

	private void callGetBuddyInfos(UUIDMsg buddyUUID) {
		GetBuddyInfosReq getBuddyInfosReq = new GetBuddyInfosReq();
		getBuddyInfosReq.setPredicate(new Common.UUIDSlicePredicate().addId(buddyUUID));
		getBuddyInfosReq.addProperty(Common.USER_PROPERTY_NAME)
						.addProperty(Common.USER_PROPERTY_PROFILE_IMAGE)
						.addProperty(Common.USER_PROPERTY_BIRTHDAY)
						.addProperty(Common.USER_PROPERTY_STATUS);
		// TcpEnvelope!
		TcpEnvelope reqEnvelope = new TcpEnvelope.Builder()
			.setType(TcpEnvelope.REQUEST)
			.setMethodId(Session.Contact.GetBuddyInfos)
			.setMessage(getBuddyInfosReq)
			.setCallback(makeNewCallback())
			.build();
		// Send!
		TcpClient.send(reqEnvelope);
	}

	/**
	 * 작업을 마치는 예제.
	 */
	private void finishMyJob() {
		if(mFinishCount <= 1){			
			finish();	// 넌 죽었음.
		}else{
			mFinishCount--;
		}
	}
	
	private void getAllBuddies(){
		GetBuddyInfosReq getBuddyInfosReq = new GetBuddyInfosReq();
		getBuddyInfosReq.setPredicate(new Common.UUIDSlicePredicate().setSliceRange((new Common.UUIDSliceRange().setAscending(true).setMaxCount(GetBuddyInfosTask.GET_BUDDY_MAX_COUNT))));
		getBuddyInfosReq.addProperty(Common.USER_PROPERTY_NAME).addProperty(Common.USER_PROPERTY_PROFILE_IMAGE).addProperty(Common.USER_PROPERTY_STATUS).addProperty(Common.USER_PROPERTY_BIRTHDAY);
		
		GetBuddyInfosTask task = new GetBuddyInfosTask(mContext, new Handler(), getBuddyInfosReq);
		task.execute();
	}
}
